﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using System.IO;
using System.Xml;
using SharePointOfView.Utilities;
using SharePointOfView.Diagnostics;
using SharePointOfView.ExtensionMethods;
using Microsoft.SharePoint.Administration;
using System.Globalization;

namespace SharePointOfView.EventReceivers
{
    /// <summary>
    /// This is a feature handler which should be paired
    /// with a content type feature.
    ///
    /// We have identified a problem with Content Types,
    /// where the content type site columns are not pushed
    /// down to custom list definitions, until they are
    /// "modified" first.
    ///
    /// This feature will interrogate all of the associated
    /// xml files that are attached to the feature.
    /// Once found, it will "modify" each of the custom fields
    /// that are referenced.
    ///
    /// This should allow list definitions to use the content
    /// type columns, without declaring them in the schema.xml
    /// 
    /// http://mkeeper.spaces.live.com/blog/cns!60F12A60288E5607!280.entry
    /// </summary>
    public class ContentTypeUpdaterFeatureReceiver : SPFeatureReceiver
    {
        /// <summary>
        /// Occurs after a Feature is activated.
        /// Loop through each of the elements in the feature
        /// Retrieve the xml content for the feature element
        /// Grab a new Content Type object
        /// Loop through each sub-node in the Content Type file
        /// Retrieve the SPField object
        /// Remove the SPField, Update the ContentType and its Childs, Add the Field and Update again
        /// 
        /// Creator : Martin Hatch (http://mkeeper.spaces.live.com/blog/cns!60F12A60288E5607!280.entry)
        /// </summary>
        /// <param name="properties">The properties.</param>
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPSite site = properties.Feature.Parent as SPSite;
            SPWeb web = site.RootWeb;

            try
            {
                
                foreach (SPElementDefinition element in properties.Definition.GetElementDefinitions(CultureInfo.CurrentCulture))
                {
                    #region Loop through feature elements
                    XmlNode content = element.XmlDefinition;
                    if (content.Name == "ContentType")
                    {
                        string strCTypeID = content.Attributes["ID"].Value;
                        SPContentType cType = web.ContentTypes[new SPContentTypeId(strCTypeID)];
                        #region Get FieldRef Order from Content type
                        string[] fieldOrder = new string[cType.FieldLinks.Count];
                        int x = 0;
                        foreach (SPFieldLink fieldlink in cType.FieldLinks)
                        {
                            fieldOrder[x] = fieldlink.Name;
                            x++;
                        }
                        #endregion
                        #region Add new columns to the content type
                        foreach (XmlNode node in content.ChildNodes)
                        {
                            #region loop through sub nodes
                            if (node.Name == "FieldRefs")
                            {
                                foreach (XmlNode fieldRef in node.ChildNodes)
                                {
                                    #region Loop through FieldRefs
                                    if (fieldRef.Name == "FieldRef")
                                    {
                                        string fieldID = fieldRef.Attributes["ID"].Value;
                                        SPField field = cType.Fields[new Guid(fieldID)];
                                        cType.FieldLinks.Delete(new Guid(fieldID));
                                        cType.Update(true);
                                        cType.FieldLinks.Add(new SPFieldLink(field));
                                        cType.Update(true);
                                    }
                                    #endregion
                                }

                            }
                            #endregion
                        }
                        #endregion
                        #region Apply Reorder
                        // reset the field order, it is possible that adding and removing fields would have affected this
                        //cType.FieldLinks.Reorder(fieldOrder);
                        // force update of the content type, pushing down to children
                        //cType.Update(true);
                        #endregion
                    }
                    #endregion
                }
            }
            catch (Exception ex)
            {
                ULS.WriteError("Error activating ContentTypeUpdater feature. Message : " + ex.Message, "SharePointOfView");
                site.Features.Remove(properties.Feature.DefinitionId);
                throw ex;
            }
            finally
            {
                web.Dispose();
            }
        }

        #region Not Used
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
        }
        public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        {
        }
        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        {
        }
        #endregion
    }
}
